﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            FindList();
            Console.Read();
        }


        public static List<User> FindList()
        {
            var list = new List<User>()
            {
                new User(){Id=1001,Name = "A",Age=38},
                new User(){Id=1002,Name = "C",Age=48},
                new User(){Id=1002,Name = "C",Age=28},
                new User(){Id=1003,Name = "B",Age=58},
                new User(){Id=1003,Name = "E",Age=58},
                new User(){Id=1003,Name = "E",Age=48},
                new User(){Id=1003,Name = "E",Age=68},
                new User(){Id=1005,Name = "D",Age=48},
            };

            MethodCallExpression resultExp = null;
            var tempData = list.AsQueryable();
            List<Pagination> orderByFielList = new List<Pagination>
            {
                new Pagination() {FieldName = "Id", OrderByType = OrderByType.Asc, Func = item => item.Id},
                new Pagination() {FieldName = "Name", OrderByType = OrderByType.Desc,Func = item => item.Name},
                new Pagination() {FieldName = "Age", OrderByType = OrderByType.Desc,Func = item => item.Age}
            };

            var index = 0;

            IOrderedQueryable<User> order = null;
            foreach (var item in orderByFielList)
            {
                if (index == 0)
                {
                    if (item.OrderByType == OrderByType.Asc)
                    {
                        order = tempData.OrderBy(item.Func);
                    }
                    if (item.OrderByType == OrderByType.Desc)
                    {
                        order = tempData.OrderByDescending(item.Func);
                    }
                }
                else
                {
                    if (order != null)
                    {
                        if (item.OrderByType == OrderByType.Asc)
                        {
                            order = order.ThenBy(item.Func);
                        }
                        if (item.OrderByType == OrderByType.Desc)
                        {
                            order = order.ThenByDescending(item.Func);
                        }
                    }
                }

                index++;
            }

            //tempData = tempData.OrderBy(item => item.Id).ThenByDescending(item => item.Name).ThenBy(item => item.Age);
            var data = order != null ? order.ToList() : tempData.ToList();
            foreach (var user in data)
            {
                Console.WriteLine("{0}-{1}-{2}", user.Id, user.Name, user.Age);
            }

            return tempData.ToList();
        }

        /*public List<TEntity> FindList(Pagination pagination)
        {
            bool isAsc = pagination.sord.ToLower() == "asc" ? true : false;
            string[] _order = pagination.sidx.Split(',');
            MethodCallExpression resultExp = null;
            var tempData = dbcontext.Set<TEntity>().AsQueryable();
            foreach (string item in _order)
            {
                string _orderPart = item;
                _orderPart = Regex.Replace(_orderPart, @"\s+", " ");
                string[] _orderArry = _orderPart.Split(' ');
                string _orderField = _orderArry[0];
                bool sort = isAsc;
                if (_orderArry.Length == 2)
                {
                    isAsc = _orderArry[1].ToUpper() == "ASC" ? true : false;
                }
                var parameter = Expression.Parameter(typeof(TEntity), "t");
                var property = typeof(TEntity).GetProperty(_orderField);
                var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                var orderByExp = Expression.Lambda(propertyAccess, parameter);
                resultExp = Expression.Call(typeof(Queryable), isAsc ? "OrderBy" : "OrderByDescending", new Type[] { typeof(TEntity), property.PropertyType }, tempData.Expression, Expression.Quote(orderByExp));
            }
            tempData = tempData.Provider.CreateQuery<TEntity>(resultExp);
            pagination.records = tempData.Count();
            tempData = tempData.Skip<TEntity>(pagination.rows * (pagination.page - 1)).Take<TEntity>(pagination.rows).AsQueryable();
            return tempData.ToList();
        }
        public List<TEntity> FindList(Expression<Func<TEntity, bool>> predicate, Pagination pagination)
        {
            bool isAsc = pagination.sord.ToLower() == "asc" ? true : false;
            string[] _order = pagination.sidx.Split(',');
            MethodCallExpression resultExp = null;
            var tempData = dbcontext.Set<TEntity>().Where(predicate);
            foreach (string item in _order)
            {
                string _orderPart = item;
                _orderPart = Regex.Replace(_orderPart, @"\s+", " ");
                string[] _orderArry = _orderPart.Split(' ');
                string _orderField = _orderArry[0];
                bool sort = isAsc;
                if (_orderArry.Length == 2)
                {
                    isAsc = _orderArry[1].ToUpper() == "ASC" ? true : false;
                }
                var parameter = Expression.Parameter(typeof(TEntity), "t");
                var property = typeof(TEntity).GetProperty(_orderField);
                var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                var orderByExp = Expression.Lambda(propertyAccess, parameter);
                resultExp = Expression.Call(typeof(Queryable), isAsc ? "OrderBy" : "OrderByDescending", new Type[] { typeof(TEntity), property.PropertyType }, tempData.Expression, Expression.Quote(orderByExp));
            }
            tempData = tempData.Provider.CreateQuery<TEntity>(resultExp);
            pagination.records = tempData.Count();
            tempData = tempData.Skip<TEntity>(pagination.rows * (pagination.page - 1)).Take<TEntity>(pagination.rows).AsQueryable();
            return tempData.ToList();
        }*/
    }

    public class User
    {
        public long Id { get; set; }
        public string Name { get; set; }

        public int Age { get; set; }
    }

    public class Pagination
    {
        public string FieldName { get; set; }

        public OrderByType OrderByType { get; set; }

        public Expression<Func<User, object>> Func { get; set; }
    }

    public enum OrderByType
    {
        Asc,
        Desc
    }
}
